package com.haojiang.mh.widget.chart;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.text.TextPaint;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;
import androidx.annotation.Nullable;
import com.haojiang.mh.R;
import com.haojiang.mh.service.entity.StartEndStateBean;
import com.haojiang.mh.service.entity.StatusBean;
import com.haojiang.mh.service.entity.TimeValueBean;
import com.haojiang.mh.utils.ImageUtil;
import com.haojiang.mh.utils.MUtil;
import com.haojiang.mh.utils.SizeUtil;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

/**
 * 双层（背景镜像+上下Y轴+图表线条呈现）
 * 当前用在《体征详情--体动模块》
 */
public class BodyMoveMirrorChartView extends View {

    //文本画笔
    private TextPaint textPaint;
    //背景柱状、数据线、坐标刻度、X轴背景 画笔
    private Paint columnPaint, linePaint, coordinatePaint, xBgPaint;
    //深睡眠、浅睡眠、rem、清醒 柱状颜色
    private int deepColor, lightColor, remColor, awakeColor;
    private int commonColor, upLineColor, downLineColor, xBgColor;
    //当前View的宽、高、默认宽、默认高、绘制区域高度、顶部和底部间隔
    private int width, height, defaultWidth, defaultHeight, drawHeight, viewPadding;
    //x轴高度、X轴文本宽、X轴文本高、右侧Y轴部分宽度、Y轴文字高度
    private int xAxisHeight, xAxisTextWidth, xAxisTextHeight, yAxisWidth, yAxisTextHeight;
    private int xColumnNumber, xStartCoordinate = -1, xEndCoordinate = -1;//X轴坐标个数、开始坐标、结束坐标
    //Y轴起始坐标、坐标间隔、除起点外坐标个数、最大值坐标
    private int yStartCoordinate, yInterval, yCoordinateNum, yMaxCoordinate;
    private int upStartY, downStartY;//上部分
    private float xItemWidth, yItemHeight;//X轴、Y轴坐标间隔
    private int columnRadius;//背景柱圆角半径
    private Path path = new Path();

    private List<StartEndStateBean> sleepList;//背景数据集
    private List<TimeValueBean> moveList;//微小体动数据集
    private List<TimeValueBean> revolveList;//翻身数据集
    private Bitmap noDataBitmap;

    public BodyMoveMirrorChartView(Context context) {
        this(context, null);
    }

    public BodyMoveMirrorChartView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public BodyMoveMirrorChartView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        @SuppressLint("CustomViewStyleable")
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ChartModuleAttribute, defStyleAttr, 0);
        yStartCoordinate = a.getInt(R.styleable.ChartModuleAttribute_cm_y_start, 0);
        yInterval = a.getInt(R.styleable.ChartModuleAttribute_cm_y_interval, 3);
        yCoordinateNum = a.getInt(R.styleable.ChartModuleAttribute_cm_y_number, 4);
        a.recycle();

        initView(context);
    }

    private void initView(Context context) {

        xAxisHeight = SizeUtil.dp2px(context, 3);
        xAxisTextWidth = SizeUtil.dp2px(context, 40);
        xAxisTextHeight = SizeUtil.dp2px(context, 30);
        yAxisWidth = SizeUtil.dp2px(context, 30);
        yAxisTextHeight = SizeUtil.dp2px(context, 20);
        drawHeight = SizeUtil.dp2px(context, 70);
        viewPadding = SizeUtil.dp2px(context, 10);
        columnRadius = SizeUtil.dp2px(context, 2);

        defaultWidth = SizeUtil.dp2px(context, 340);

        noDataBitmap = ImageUtil.getBitmapFromDrawable(context, R.drawable.img_no_chart_data);
        defaultHeight = noDataBitmap.getHeight();
        deepColor = getResources().getColor(R.color.purple_5) & 0x4CFFFFFF;
        lightColor = getResources().getColor(R.color.purple_3) & 0x4CFFFFFF;
        remColor = getResources().getColor(R.color.purple_2) & 0x4CFFFFFF;
        awakeColor = getResources().getColor(R.color.grey_3) & 0x4CFFFFFF;
        commonColor = getResources().getColor(R.color.white) & 0x33FFFFFF;
        upLineColor = getResources().getColor(R.color.white);
        downLineColor = getResources().getColor(R.color.purple_2);
        xBgColor = getResources().getColor(R.color.grey_5);

        textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
        textPaint.setTextAlign(Paint.Align.CENTER);
        textPaint.setColor(commonColor);
        textPaint.setTextSize(SizeUtil.sp2px(context, 12));

        columnPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        columnPaint.setStyle(Paint.Style.FILL);

        linePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        linePaint.setStyle(Paint.Style.FILL);
        linePaint.setStrokeWidth(SizeUtil.dp2px(context, 1));

        coordinatePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        coordinatePaint.setStyle(Paint.Style.FILL);
        coordinatePaint.setColor(commonColor);

        xBgPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        xBgPaint.setStyle(Paint.Style.FILL);
        xBgPaint.setColor(xBgColor);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        width = w;
        height = h;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        if (sleepList == null || sleepList.isEmpty() || xStartCoordinate == -1 || xEndCoordinate == -1) {
            canvas.drawBitmap(noDataBitmap, (width - noDataBitmap.getWidth()) *0.5f, 0, linePaint);
            return;
        }

        xItemWidth = (float) (width - yAxisWidth) / xColumnNumber;
        yItemHeight = (float) drawHeight / yCoordinateNum;
        yMaxCoordinate = yStartCoordinate + yInterval * yCoordinateNum;
        upStartY = viewPadding + drawHeight;
        downStartY = height - viewPadding - drawHeight;

        /* 绘制X轴 */
        drawXAxis(canvas);

        /* 绘制X轴 */
        drawYAxis(canvas);

        /* 绘制背景柱状图 */
        drawBgColumn(canvas);

        /* 绘制上部分和下部分线 */
        drawUpDownLine(canvas);
    }

    /**
     * 绘制X轴
     */
    private void drawXAxis(Canvas canvas) {
        canvas.drawRect(0, viewPadding + drawHeight, width, height - viewPadding - drawHeight, xBgPaint);//背景带
        int interval;
        if (xColumnNumber <= 6) {
            interval = 1;
        } else if (xColumnNumber <= 18) {
            interval = 2;
        } else {
            interval = 3;
        }
        if (xColumnNumber == 1) {//只有一个小时，左右刻度+左右靠边时间点
            /* 上部分 */
            canvas.drawLine(0, upStartY, 0, upStartY + xAxisHeight, coordinatePaint);
            canvas.drawLine(width - yAxisWidth, upStartY, width - yAxisWidth, upStartY + xAxisHeight, coordinatePaint);
            /* 下部分 */
            canvas.drawLine(0, downStartY, 0, downStartY - xAxisHeight, coordinatePaint);
            canvas.drawLine(width - yAxisWidth, downStartY, width - yAxisWidth, downStartY - xAxisHeight, coordinatePaint);
            /* 公共文字部分 */
            canvas.drawText(
                    String.format(Locale.getDefault(), "%02d:00", xStartCoordinate % 24),
                    xAxisTextWidth *0.5f,
                    SizeUtil.getBaseLine(textPaint, upStartY + xAxisTextHeight, xAxisTextHeight),
                    textPaint
            );//最左侧刻度
            canvas.drawText(
                    String.format(Locale.getDefault(), "%02d:00", xEndCoordinate % 24),
                    width - yAxisWidth - xAxisTextWidth *0.5f,
                    SizeUtil.getBaseLine(textPaint, upStartY + xAxisTextHeight, xAxisTextHeight),
                    textPaint
            );//最右侧刻度
        } else {//绘制所有刻度以及除顶末端的刻度文字
            for (int i = 0; i <= xColumnNumber; i++) {
                canvas.drawLine(i * xItemWidth, upStartY, i * xItemWidth, upStartY + xAxisHeight, coordinatePaint);
                canvas.drawLine(i * xItemWidth, downStartY, i * xItemWidth, downStartY - xAxisHeight, coordinatePaint);
                if (i != 0 && i != xColumnNumber && i % interval == 0) {
                    canvas.drawText(
                            String.format(Locale.getDefault(), "%02d:00", (xStartCoordinate + i) % 24),
                            xItemWidth * i,
                            SizeUtil.getBaseLine(textPaint, upStartY + xAxisTextHeight, xAxisTextHeight),
                            textPaint
                    );
                }
            }
        }
    }

    /**
     * 绘制Y轴
     */
    private void drawYAxis(Canvas canvas) {
        for (int i = 0; i <= yCoordinateNum; i++) {
            float yUpItemMidPos = upStartY - yItemHeight * i;
            float yDownItemMidPos = downStartY + yItemHeight * i;
            canvas.drawCircle(width - yAxisWidth, yUpItemMidPos, 5, coordinatePaint);//刻度点
            canvas.drawCircle(width - yAxisWidth, yDownItemMidPos, 5, coordinatePaint);
            if (i == 0) continue;
            canvas.drawText(//X轴上部分
                    String.valueOf(yStartCoordinate + i * yInterval),
                    width - yAxisWidth *0.5f,
                    SizeUtil.getBaseLine(textPaint, yUpItemMidPos + yAxisTextHeight *0.5f, yAxisTextHeight),
                    textPaint
            );
            canvas.drawText(//X轴上部分
                    String.valueOf(yStartCoordinate + i * yInterval),
                    width - yAxisWidth *0.5f,
                    SizeUtil.getBaseLine(textPaint, yDownItemMidPos + yAxisTextHeight *0.5f, yAxisTextHeight),
                    textPaint
            );
        }
    }

    /**
     * 绘制背景折线图
     */
    private void drawBgColumn(Canvas canvas) {
        int columnColor = 0, columnHeight = 0;
        for (int i = 0; i < sleepList.size(); i++) {
            StartEndStateBean ssb = sleepList.get(i);
            if (ssb.getStatus() == 4 || ssb.getStatus() == 5) continue;
            switch (ssb.getStatus()) {
                case 0://深睡眠
                    columnColor = deepColor;
                    columnHeight = drawHeight;
                    break;
                case 1://浅睡眠
                    columnColor = lightColor;
                    columnHeight = drawHeight * 3 / 4;
                    break;
                case 2://REM
                    columnColor = remColor;
                    columnHeight = drawHeight * 5 / 12;
                    break;
                case 3://清醒
                    columnColor = awakeColor;
                    columnHeight = drawHeight / 8;
                    break;
            }
            float start = getXCoordinate(ssb.getStart());
            float end = getXCoordinate(ssb.getEnd());
            path.reset();
            columnPaint.setColor(columnColor);
            if (end - start <= columnRadius * 2) {
                path.moveTo(start, upStartY);
                path.lineTo(start, upStartY - columnHeight);
                path.lineTo(end, upStartY - columnHeight);
                path.lineTo(end, upStartY);
                canvas.drawPath(path, columnPaint);
                path.reset();
                path.moveTo(start, downStartY);
                path.lineTo(start, downStartY + columnHeight);
                path.lineTo(end, downStartY + columnHeight);
                path.lineTo(end, downStartY);
                canvas.drawPath(path, columnPaint);
            } else {
                path.moveTo(start, upStartY);
                path.lineTo(start, upStartY - columnHeight + columnRadius);
                path.quadTo(start, upStartY - columnHeight, start + columnRadius, upStartY - columnHeight);
                path.lineTo(end - columnRadius, upStartY - columnHeight);
                path.quadTo(end, upStartY - columnHeight, end, upStartY - columnHeight + columnRadius);
                path.lineTo(end, upStartY);
                canvas.drawPath(path, columnPaint);
                path.reset();
                path.moveTo(start, downStartY);
                path.lineTo(start, downStartY + columnHeight - columnRadius);
                path.quadTo(start, downStartY + columnHeight, start + columnRadius, downStartY + columnHeight);
                path.lineTo(end - columnRadius, downStartY + columnHeight);
                path.quadTo(end, downStartY + columnHeight, end, downStartY + columnHeight - columnRadius);
                path.lineTo(end, downStartY);
                canvas.drawPath(path, columnPaint);
            }
        }
    }

    /**
     * 绘制上部分和下部分线
     */
    private void drawUpDownLine(Canvas canvas) {
        if (revolveList != null) {
            linePaint.setColor(upLineColor);
            for (TimeValueBean move : moveList) {
                if (move.getValue() <= yStartCoordinate) continue;
                int moveValue = move.getValue() > yMaxCoordinate ? yMaxCoordinate : move.getValue();
                float xUp = getXCoordinate(move.getTime());
                if (xUp < 0 || xUp > width - yAxisWidth) continue;
                float yUp = viewPadding + (float) (yMaxCoordinate - moveValue) * drawHeight / (yMaxCoordinate - yStartCoordinate);
                canvas.drawLine(xUp, upStartY, xUp, yUp, linePaint);
            }
        }
        if (moveList != null) {
            linePaint.setColor(downLineColor);
            for (TimeValueBean revolve : revolveList) {
                if (revolve.getValue() <= yStartCoordinate) continue;
                int revolveValue = revolve.getValue() > yMaxCoordinate ? yMaxCoordinate : revolve.getValue();
                float xDown = getXCoordinate(revolve.getTime());
                if (xDown < 0 || xDown > width - yAxisWidth) continue;
                float yDown = height - viewPadding - (float) (yMaxCoordinate - revolveValue) * drawHeight / (yMaxCoordinate - yStartCoordinate);
                canvas.drawLine(xDown, downStartY, xDown, yDown, linePaint);
            }
        }
    }

    /**
     * 获取时间轴坐标
     *
     * @param timeString 时间点
     * @return 相对x坐标点
     */
    private float getXCoordinate(String timeString) {
        int duration = MUtil.INSTANCE.getTimeDuration(xStartCoordinate, timeString, "HH:mm");
        return (float) (duration * (width - yAxisWidth)) / (3600 * xColumnNumber);
    }

    /**
     * 获取X轴坐标个数
     */
    private void getXColumnNumber() {
        if (sleepList == null || sleepList.isEmpty()) return;
        String startTime = sleepList.get(0).getStart();
        if (TextUtils.isEmpty(startTime) || !startTime.contains(":")) {
            xStartCoordinate = -1;
            return;
        } else {
            xStartCoordinate = MUtil.INSTANCE.getHourAndMinute(startTime, "HH:mm")[0];
        }
        String endTime = sleepList.get(sleepList.size() - 1).getEnd();
        if (TextUtils.isEmpty(endTime) || !endTime.contains(":")) {
            xEndCoordinate = -1;
            return;
        } else {
            int[] endHM = MUtil.INSTANCE.getHourAndMinute(endTime, "HH:mm");
            xEndCoordinate = endHM[0] + (endHM[1] != 0 ? 1 : 0);
        }
        if (xStartCoordinate == xEndCoordinate) {
            xColumnNumber = 24;
        } else {
            xColumnNumber = xEndCoordinate - xStartCoordinate;
            if (xEndCoordinate < xStartCoordinate) xColumnNumber += 24;
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        setMeasuredDimension(
                getMeasuredLength(widthMeasureSpec, true),
                getMeasuredLength(heightMeasureSpec, false)
        );
    }

    private int getMeasuredLength(int length, boolean isWidth) {
        int specMode = MeasureSpec.getMode(length);
        int specSize = MeasureSpec.getSize(length);
        int size;
        int padding = isWidth ? getPaddingLeft() + getPaddingRight() : getPaddingTop() + getPaddingBottom();
        if (specMode == MeasureSpec.EXACTLY) {
            size = specSize;
        } else if (specMode == MeasureSpec.UNSPECIFIED) {
            size = isWidth ? defaultWidth : defaultHeight;
        } else {
            size = isWidth ? padding + defaultWidth : padding + defaultHeight;
            if (specMode == MeasureSpec.AT_MOST) {
                size = Math.min(size, specSize);
            }
        }
        return size;
    }

    public void setChartDataNew(List<StatusBean> bgData, List<TimeValueBean> moveData, List<TimeValueBean> revolveData) {
        if (sleepList == null) sleepList = new ArrayList<>();
        sleepList.clear();
        if (moveList == null) moveList = new ArrayList<>();
        moveList.clear();
        if (revolveList == null) revolveList = new ArrayList<>();
        revolveList.clear();

        if (bgData != null&& !bgData.isEmpty()) {
            List<StartEndStateBean> tempList = new ArrayList<>();
            for (StatusBean data : bgData) {
                StartEndStateBean ses = new StartEndStateBean();
                ses.setStart(MUtil.INSTANCE.getHM(data.getStart()));
                ses.setEnd(MUtil.INSTANCE.getHM(data.getEnd()));
                ses.setStatus(data.getStatus());
                tempList.add(ses);
            }
            sleepList.addAll(tempList);
        }
        if (moveData != null) moveList.addAll(moveData);
        if (revolveData != null) revolveList.addAll(revolveData);
        getXColumnNumber();

        defaultHeight = viewPadding * 2 + drawHeight * 2 + xAxisTextHeight;
        requestLayout();
    }

    public void setChartData(List<StartEndStateBean> bgData, List<TimeValueBean> moveData, List<TimeValueBean> revolveData) {
        if (sleepList == null) sleepList = new ArrayList<>();
        sleepList.clear();
        if (moveList == null) moveList = new ArrayList<>();
        moveList.clear();
        if (revolveList == null) revolveList = new ArrayList<>();
        revolveList.clear();

        if (bgData != null) sleepList.addAll(bgData);
        if (moveData != null) moveList.addAll(moveData);
        if (revolveData != null) revolveList.addAll(revolveData);
        getXColumnNumber();

        defaultHeight = viewPadding * 2 + drawHeight * 2 + xAxisTextHeight;
        requestLayout();
    }

    public void showNoData() {
        if (sleepList == null) sleepList = new ArrayList<>();
        sleepList.clear();
        if (moveList == null) moveList = new ArrayList<>();
        moveList.clear();
        if (revolveList == null) revolveList = new ArrayList<>();
        revolveList.clear();
        defaultHeight = noDataBitmap.getHeight();
        requestLayout();
    }
}
